/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.lock.service.memory;

import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.transaction.JpaTransaction;
import io.iec.edp.caf.commons.transaction.TransactionPropagation;
import io.iec.edp.caf.core.context.BizContextManager;
import io.iec.edp.caf.core.session.ICafSessionService;
import io.iec.edp.caf.lock.service.api.api.*;
import io.iec.edp.caf.lockservice.api.LockStatus;
import io.iec.edp.caf.lockservice.api.ReplacedScope;
import io.iec.edp.caf.lock.service.api.exception.DLErrorDefinition;
import io.iec.edp.caf.lock.service.api.exception.DistributedLockException;
import io.iec.edp.caf.lock.service.api.repositories.BatchLockRepo;
import io.iec.edp.caf.lock.service.api.repositories.LockRepo;
import io.iec.edp.caf.lock.service.api.utils.DataValidator;
import io.iec.edp.caf.lockservice.api.*;
import lombok.var;
import org.springframework.lang.Nullable;

import java.io.IOException;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 内存锁服务实现类
 *
 * @author wangyandong
 */

public class MemoryLockServiceImpl implements LockService {

    private DistributedLockFactory factory;
    private ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
    private LockRepo repo;
    private BatchLockRepo batchRepo;
    private BizContextManager bizContextManager;
    private ICafSessionService sessionService;


    public MemoryLockServiceImpl(DistributedLockFactory factory,
                                 BizContextManager bizContextManager, ICafSessionService sessionService, LockRepo repo,
                                 BatchLockRepo batchRepo) {
        this.factory = factory;
        this.bizContextManager = bizContextManager;
        this.sessionService = sessionService;
        this.repo = repo;
        this.batchRepo = batchRepo;
    }

    @Override
    public LockResult addLock(String mkId, String dataCat, String dataId, DataLockOptions option, String funcId, String comment, @Nullable DistributedLockOptions distributedLockOptions) {
        DataValidator.checkForEmptyString(mkId, "mkId");
        DataValidator.checkForEmptyString(dataCat, "dataCat");
        DataValidator.checkForEmptyString(dataId, "dataId");
        DataValidator.checkForNullReference(option, "options");
        LockResult result = this.internalAddLock(mkId, dataCat, dataId, option, funcId, comment, null, distributedLockOptions);

        return result;
    }

    /**
     * @param mkId    模块ID
     * @param dataCat 数据种类
     * @param dataId  数据ID
     * @param option  数据锁的设置选项
     * @param funcId  加锁的功能Id
     * @param comment 备注
     * @return
     */
    @Override
    public LockResult addLock(String mkId, String dataCat, String dataId, DataLockOptions option, String funcId, String comment) {
        return this.addLock(mkId, dataCat, dataId, option, funcId, comment, null);
    }

    @Override
    @Deprecated
    public BatchLockResult addBatchLock(String mkId, String dataCat, List<String> dataIds, String groupId, DataLockOptions option, String funcId, String comment, @Nullable DistributedLockOptions distributedLockOptions) {
        return this.addBatchLock(mkId, dataCat, dataIds, groupId, option.getPersistenceTime(), funcId, comment);
    }

    @Override
    @Deprecated
    public BatchLockResult addBatchLock(String mkId, String dataCat, List<String> dataIds, String groupId, DataLockOptions option, String funcId, String comment) {
        return this.addBatchLock(mkId, dataCat, dataIds, groupId, option, funcId, comment, null);
    }

    /**
     * 批量锁加锁方法
     *
     * @param mkId            模块ID
     * @param dataCat         数据种类
     * @param dataIds         数据ID列表
     * @param groupId         批量锁标识，可空
     * @param persistenceTime 持续时间
     * @param funcId          功能ID
     * @param comment         备注
     * @return
     */
    @Override
    public BatchLockResult addBatchLock(String mkId, String dataCat, List<String> dataIds, @Nullable String groupId, Duration persistenceTime, String funcId, String comment) {
        DataValidator.checkForEmptyString(mkId, "mkId");
        DataValidator.checkForEmptyString(dataCat, "dataCat");
        DataValidator.checkForNullReference(dataIds, "dataIDs");
        DataValidator.checkForNullReference(persistenceTime, "persistenceTime");

        //如果不为实例级锁，首先检查session是否在线，不在线抛异常
        if (this.isSessionNotValid(CAFContext.current.getSessionId()))
            throw new DistributedLockException("pfcomm", DLErrorDefinition.AddLock_IsSession_Error,
                    "Session:" + CAFContext.current.getSessionId() + " is not online!", null, ExceptionLevel.Error, false);

        if (groupId == null || "".equals(groupId))
            groupId = UUID.randomUUID().toString();

        BatchLockResult result = new BatchLockResult();
        // 获取持久资源
        String resource = String.format("%s-%s", mkId, dataCat);
        result.setGroupId(groupId);
        DistributedLock distributedLock = this.factory.createLock(resource, Duration.ofSeconds(20));
        //若得不到分布式锁等待
        if (distributedLock == null || !distributedLock.isAcquired()) {
            result.setLockedEntities(null);
            result.setSuccess(false);
            return result;
        }

        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            //删除已过期的锁数据
            this.batchRepo.deleteByExpiredTime(CAFContext.current.getCurrentDateTime());
            // 根据资源dataIds长度分批查询,根据当前条件查询数据
            List<BatchLockEntity> entities = queryBatchLockEntityByDataIds(mkId, dataCat, dataIds);
            //根据当前条件查询数据
            // List<BatchLockEntity> entities = this.batchRepo.findAllByMkIdAndCategoryIdAndDataIdIn(mkId, dataCat, dataIds);
            //如果entities列表不为空，则认为无法加锁
            if (entities != null && entities.size() > 0) {
                // 根据session或者contextid删除数据
                int count = deleteBatchLockBySession(entities);
                if (entities.size() != count) {
                    result.setLockedEntities(entities);
                    result.setSuccess(false);
                } else {
                    //执行加锁
                    List<BatchLockEntity> entityList = this.createBatchEntities(mkId, dataCat, dataIds, groupId, persistenceTime, funcId, comment);
                    this.batchRepo.saveAll(entityList);
                    result.setSuccess(true);
                }
            } else {
                //执行加锁
                List<BatchLockEntity> entityList = this.createBatchEntities(mkId, dataCat, dataIds, groupId, persistenceTime, funcId, comment);
                this.batchRepo.saveAll(entityList);
                result.setSuccess(true);
            }
            tran.commit();
            return result;
        } catch (Throwable e) {
            tran.rollback();
            throw e;
        }finally {
            try {
                if (distributedLock != null)
                    distributedLock.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    private List<BatchLockEntity> queryBatchLockEntityByDataIds(String mkId, String dataCat, List<String> dataIds) {
        List<BatchLockEntity> entities = new ArrayList<>();
        if (dataIds != null) {
            int size = dataIds.size();//获取dataIds的长度
            int num = size / 999 + 1;//每次查询不超过999条
            if (num == 1 || dataIds == null) {
                return this.batchRepo.findAllByMkIdAndCategoryIdAndDataIdIn(mkId, dataCat, dataIds);
            } else {
                for (int i = 0; i < num; i++) {
                    int start = i * 999;
                    int end = (i + 1) * 999;
                    if (end >= size) {
                        end = size;
                    }
                    List<BatchLockEntity> entitiesSub = this.batchRepo.findAllByMkIdAndCategoryIdAndDataIdIn(mkId, dataCat, dataIds.subList(start, end));
                    entities.addAll(entitiesSub);
                }
            }
        }
        return entities;
    }


    private int deleteBatchLockBySession(List<BatchLockEntity> entities) {
        int count = 0;
        for (BatchLockEntity entity : entities) {
            if (entity.getSessionId() != null && !"".equals(entity.getSessionId()) && CAFContext.current.getSessionId() != null && !"".equals(CAFContext.current.getSessionId())) {
                if (!entity.getSessionId().equals(CAFContext.current.getSessionId()) && this.isSessionNotValid(entity.getSessionId())) {
                    this.batchRepo.deleteById(entity.getId());
                    count += 1;
                }
            }
        }
        return count;
    }


    @Override
    @Deprecated
    public boolean removeLock(String lockId, boolean removeSharedLock, String sessionId) {
        DataValidator.checkForEmptyString(lockId, "lockId");
        return this.removeLock(lockId);
    }

    /**
     * 根据锁编号解锁
     *
     * @param lockId 锁编号
     * @return 是否成功的标识
     */
    public boolean removeLock(String lockId) {
        DataValidator.checkForEmptyString(lockId, "lockId");
        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            if (this.repo.findById(lockId).isPresent()) {
                this.repo.deleteById(lockId);
            }
            tran.commit();
            return true;
        } catch (Throwable e) {
            tran.rollback();
            throw e;
        }
    }

    @Override
    public boolean removeSessionLock(String sessionId, int tenantId) {

        DataValidator.checkForEmptyString(sessionId, "sessionId");
        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            this.repo.deleteBySessionId(sessionId);
            tran.commit();
            return true;
        } catch (Throwable ex) //没有提供sessionid调用报错a
        {
            tran.rollback();
            throw ex;
//            throw new DistributedLockException("pfcomm", DLErrorDefinition.RemLock_Sessionid_Error, null, ex, ExceptionLevel.Error, false);
        }
    }

    @Override
    public boolean removeBatchLock(String groupId) {
        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            //若批次号没对应锁则也算删锁成功
            this.batchRepo.deleteByGroupId(groupId);
            tran.commit();
            return true;
        } catch (Throwable ex) //没有提供groupid调用报错
        {
            tran.rollback();
            throw ex;
//            throw new DistributedLockException("pfcomm", DLErrorDefinition.RemLock_BathLock_Error, null, ex, ExceptionLevel.Error, false);
        }
    }

    @Override
    public boolean removeInvalidLocks(int tenantId) {
        // to do
        return true;
    }

    @Override
    public  boolean removeBatchLockByContext(String contextId){
        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            //若批次号没对应锁则也算删锁成功
            this.batchRepo.deleteByContextId(contextId);
            tran.commit();
            return true;
        } catch (Throwable ex) //没有提供groupid调用报错
        {
            tran.rollback();
            throw ex;
//            throw new io.iec.edp.caf.lockservice.api.DistributedLockException("pfcomm", DLErrorDefinition.RemLock_BathLock_Error, null, ex, ExceptionLevel.Error, false);
        }
    }

    /**
     * 删除批量锁(排他锁)
     * @param lockIDs 批量锁ID
     * @return 是否批量删锁成功
     */
    private boolean removeBatchLock(List<String> lockIDs) {
        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
            tran.begin(TransactionPropagation.REQUIRES_NEW);
            // this.batchRepo.deleteAllByIdIn(lockIDs);
            deleteBatchLockEntityByLockIDs(lockIDs);
            tran.commit();
            return true;                         //都成功或没有锁也算删锁失败
        } catch (Throwable ex) //没有提供lockids调用报错
        {
            tran.rollback();
            throw ex;
//            throw new DistributedLockException("pfcomm", DLErrorDefinition.RemLock_BathLock_Error, null, ex, ExceptionLevel.Error, false);
        }
    }

    private void deleteBatchLockEntityByLockIDs(List<String> lockIDs) {
        if (lockIDs != null) {
            int size = lockIDs.size();//获取dataIds的长度
            int num = size / 2 + 1;//每次删除不超过500条
            if (num == 1 || lockIDs == null) {
                this.batchRepo.deleteAllByIdIn(lockIDs);
            } else {
                for (int i = 0; i < num; i++) {
                    int start = i * 2;
                    int end = (i + 1) * 2;
                    if (end >= size) {
                        end = size;
                    }
                    this.batchRepo.deleteAllByIdIn(lockIDs.subList(start, end));
                }
            }
        }
    }


    /**
     * 内部执行加锁逻辑
     */
    private LockResult internalAddLock(String mkId, String dataCat, String dataId,
                                       DataLockOptions option, String funcId, String comment, String groupId, @Nullable DistributedLockOptions distributedLockOptions) {
        LockResult result = new LockResult();
        //结果默认为不成功
        result.setSuccess(false);
        //根据上下文获取租户ID
        int tenantId = CAFContext.current.getTenantId();
        DistributedLock distributedLock = null;
        //根据资源、租户等信息构造锁编号
        String lockId = UUID.randomUUID().toString();
        // 获取持久资源
        String resource = String.format("%s-%s-%s-%s", tenantId, mkId, dataCat, dataId);

        //如果不为实例级锁，首先检查session是否在线，不在线抛异常
        if (this.isSessionNotValid(CAFContext.current.getSessionId())) {
            throw new DistributedLockException("pfcomm", DLErrorDefinition.AddLock_IsSession_Error,
                    "Session:" + CAFContext.current.getSessionId() + " is not online!", null, ExceptionLevel.Error, false);
        }

        LockEntity entity = this.createLockEntity(lockId, mkId, dataCat, dataId, option, funcId, comment);
        Duration expiryTime = distributedLockOptions == null ? Duration.ofSeconds(20) : distributedLockOptions.getExpiryTime();
        try {

            distributedLock = this.factory.createLock(resource, expiryTime);
            //若得不到分布式锁则直接返回
            if (distributedLock == null || !distributedLock.isAcquired())
                throw new DistributedLockException("pfcomm", DLErrorDefinition.AddLock_IsAcquired_Error,
                        "DistributedLock get nothing!", null, ExceptionLevel.Error, false);
            JpaTransaction tran = JpaTransaction.getTransaction();
            try {
                tran.begin(TransactionPropagation.REQUIRES_NEW);
                //从数据库获取锁信息
                List<LockEntity> entities = this.repo.findByMkIdAndCategoryIdAndDataId(mkId, dataCat, dataId);

                // 无锁直接加锁
                if (entities == null || entities.size() == 0) {
                    result.setLockedEntities(null);
                    this.repo.save(entity);
                    result.setSuccess(true);
                    result.setLockId(entity.getId());
                } else {
                    //获取排它锁
                    LockStatus lockStatus = this.checkValidate(entities.get(0));

                    // 共享锁的处理 - 不检查共享锁的存在性，排它锁存在但可以被替换掉，直接删除排它锁
                    if (option.getReplacedScope() == ReplacedScope.Share) {
                        switch (lockStatus) {
                            case Shared:
                            case Unlocked:
                                this.repo.save(entity);
                                result.setSuccess(true);
                                result.setLockId(entity.getId());
                                break;
                            case Invalid:
                            case Replaceable:
                                this.repo.deleteById(entities.get(0).getId());
                                this.repo.save(entity);
                                result.setSuccess(true);
                                result.setLockId(entity.getId());
                                break;
                            case Irreplaceable:
                                result.setLockedEntities(entities);
                                result.setSuccess(false);
                                break;
                        }
                    } else {
                        //加排它锁：不存在有效的排它锁 && 不存在有效的共享锁
                        if (lockStatus == LockStatus.Irreplaceable) {
                            result.setLockedEntities(entities);
                            result.setSuccess(false);
                        } else {
                            List<LockStatus> sharedLockStatus = this.checkValidate(entities);
                            // 共享锁，在以下情况不可加锁：1、存在有效且不可替换锁、共享锁（认为不允许替换）；2、存在多个有效可替换锁；
                            boolean validSharedLockExisting = false;
                            if (entities != null && entities.size() > 0) {
                                for (int index = 0; index < entities.size(); index++) {
                                    // 锁有效且不可替换
                                    if (sharedLockStatus.get(index) == LockStatus.Irreplaceable ||
                                            sharedLockStatus.get(index) == LockStatus.Shared) {
                                        result.setLockedEntities(entities);
                                        result.setSuccess(false);
                                        validSharedLockExisting = true;
                                        break;
                                    }
                                }
                            }

                            if (validSharedLockExisting == false) {
                                //不存在有效的共享锁
                                this.repo.deleteInBatch(entities);
                                //新加锁
                                this.repo.save(entity);
                                result.setSuccess(true);
                                result.setLockId(entity.getId());

                            }
                        }
                    }
                }
                tran.commit();
                return result;
            } catch (Throwable ex) {
                tran.rollback();
                throw ex;
            }
        } catch (Throwable e) {
            throw e;
        } finally {
            try {
                if (distributedLock != null)
                    distributedLock.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private LockEntity createLockEntity(String lockId, String mkId, String dataCat, String dataId, DataLockOptions option, String funcId, String comment) {
        String sessionId = CAFContext.current.getSessionId();
        var entity = new LockEntity();
//        entity.setId(lockId);
        entity.setMkId(mkId);
        entity.setCategoryId(dataCat);
        entity.setDataId(dataId);
        entity.setKeepTime(option.getPersistenceTime());
        entity.setLockedScope(option.getLockedScope());
        entity.setReplacedScope(option.getReplacedScope());
        entity.setFuncId(funcId);
        entity.setSessionId(sessionId);
        entity.setContextId(CAFContext.current.getContextId());
        entity.setComment(comment);
        entity.setUserId(CAFContext.current.getUserId());
        entity.setLockTime(CAFContext.current.getCurrentDateTime());
        entity.setSuName(CAFContext.current.getCurrentSU());
        return entity;
    }

    private List<BatchLockEntity> createBatchEntities(String mkId, String dataCat, List<String> dataIds, String groupId, Duration persistenceTime, String funcId, String comment) {
        List<BatchLockEntity> entities = new ArrayList<>();
        OffsetDateTime lockTime = CAFContext.current.getCurrentDateTime();
        OffsetDateTime expiredTime = (persistenceTime.getSeconds() == 0) ?
                OffsetDateTime.of(2037, 1, 19, 3, 14, 7, 59, ZoneOffset.UTC) : lockTime.plus(persistenceTime.getSeconds(), ChronoUnit.SECONDS);

        String sessionId = CAFContext.current.getSessionId();
        String contextId = CAFContext.current.getContextId();
        for (var dataId : dataIds) {
            var entity = new BatchLockEntity();
            entity.setId(UUID.randomUUID().toString());
            entity.setMkId(mkId);
            entity.setCategoryId(dataCat);
            entity.setDataId(dataId);
            entity.setGroupId(groupId);
            entity.setSessionId(sessionId);
            entity.setContextId(contextId);
            entity.setFuncId(funcId);
            entity.setComment(comment);
            entity.setExpiredTime(expiredTime);
            entity.setLockTime(lockTime);
            entity.setUserId(CAFContext.current.getUserId());
            entity.setSuName(CAFContext.current.getCurrentSU());
            // entity.setLocknavigationId(locknavigationid);
            entities.add(entity);
        }
        return entities;
    }

    /**
     * 检查上下文是否有效
     *
     * @param contextId
     * @return 上下文的有效状态
     */
    private boolean isContextNotValid(String contextId) {
        return bizContextManager.isExpired(contextId);
    }

    /**
     * 检查会话是否有效
     *
     * @param sessionId
     * @return 会话的有效状态
     */
    private boolean isSessionNotValid(String sessionId) {
        //return true;
        return sessionService.isExpired(sessionId);
    }

    /**
     * 检查批量锁的有效状态
     * @param locks
     * @return 锁的有效状态
     */
    private List<LockStatus> checkValidate(List<LockEntity> locks) {
        List<LockStatus> result = new ArrayList<>();
        if (locks != null && locks.size() > 0) {
            for (int i = 0; i < locks.size(); i++) {
                result.add(checkValidate(locks.get(i)));
            }
        }
        return result;
    }


    /**
     * 检查锁是否有效
     * @param lockEntity
     * @return 锁状态：Unlocked为锁不存在；Invalid为锁已失效；Replaceable为锁有效可替换；Irreplaceable为锁有效不可替换；Shared为共享锁，可以加锁。
     */
    private LockStatus checkValidate(LockEntity lockEntity) {
        LockStatus result = LockStatus.Invalid;
        //1 锁不存在
        if (lockEntity == null) {
            return LockStatus.Unlocked;
        }
        //2 根据时间判断是否无效
        long seconds = lockEntity.getKeepTime().getSeconds();
        OffsetDateTime lockedTime = lockEntity.getLockTime();
        OffsetDateTime expirationTime = lockedTime.plus(seconds, ChronoUnit.SECONDS);
        OffsetDateTime currentTime = CAFContext.current.getCurrentDateTime();
        if (seconds != 0 && (currentTime.compareTo(expirationTime) >= 0)) {
            return LockStatus.Invalid;                           // 表示锁存在但无效,后续可以加锁
        } else                                                              // 表示锁存在且有效，需要再检查
        {
            //3 根据范围(LockedScope)判断是否有效
            String locksessionId = lockEntity.getSessionId();
            String contextId = lockEntity.getContextId();
            String currentsessionId = CAFContext.current.getSessionId();
            String currentContextId = CAFContext.current.getContextId();
            switch (lockEntity.getLockedScope()) {
                case AppInstance:                             // 表示实例锁有效，需要近一步检查
                    result = LockStatus.Replaceable;
                    break;
                case Session:
                    if (!locksessionId.equals(currentsessionId) && this.isSessionNotValid(locksessionId)) {
                        return LockStatus.Invalid;               // 表示锁存在但进程丢失,后续可以加锁
                    }
                    result = LockStatus.Replaceable;
                    break;                                                // 进程锁需要进一步检查
                case BizContext:                                          // 功能上下文
                    if (!contextId.equals(currentContextId) && this.isContextNotValid(contextId)) {
                        return LockStatus.Invalid;               // 表示锁存在但context无效,后续可以加锁
                    }
                    result = LockStatus.Replaceable;
                    break;
                default:
                    result = LockStatus.Invalid;
                    break;
            }
            //4 根据范围(ReplacedScope)判断是否可以替换
            String lockuserCode = lockEntity.getUserId();
            String currentuserCode = CAFContext.current.getUserId();
            switch (lockEntity.getReplacedScope()) {
                case Exclusive:                             // 独占锁，不允许后续加锁
                    result = LockStatus.Irreplaceable;
                    return result;
                case Session:                               // 进程锁，如果本进程内可替换
                    if (!locksessionId.equals(currentsessionId)) {
                        result = LockStatus.Irreplaceable;                // 其它进程的锁，不可加锁
                        return result;
                    }
                    break;
                case Self:                                  // 同一用户可替换，可能多个进程用同一用户登录
                    if (!currentuserCode.equals(lockuserCode)) {
                        result = LockStatus.Irreplaceable;                // 其它用户锁，不可加锁
                        return result;
                    }
                    break;
                case Share:                                 // 共享锁，可加锁
                    return LockStatus.Shared;
            }
            return result;
        }
    }

    public LockStatus getLockStatus (LockEntity lockEntity) {
        return  checkValidate(lockEntity);
    }

    /**
     * 根据gropuId获取dataIds
     * @param groupId
     * @return
     */
    @Override
    public List<String>  getDataIds(String groupId){

        DataValidator.checkForEmptyString(groupId, "groupId");

        //清理过期锁
        this.batchRepo.deleteByExpiredTime(CAFContext.current.getCurrentDateTime());

        List<String> listDataIds=new ArrayList<>();

        List<BatchLockEntity>  batchLockEntities=this.batchRepo.findByGroupId(groupId);
        for(BatchLockEntity batchLockEntity:batchLockEntities){
            listDataIds.add(batchLockEntity.getDataId());
        }
        return  listDataIds;

    }
}
